/**
 * 文件名：@SimpleExceptionProcessor.java <br/>
 * 包名：cn.efunbox.afw.core.exception.handler <br/>
 * 项目名：afw-core <br/>
 * @author xtwin <br/>
 */
package cn.efunbox.afw.core.exception.handler;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import cn.efunbox.afw.core.ErrorModel;
import cn.efunbox.afw.core.ErrorModel.ErrorField;
import cn.efunbox.afw.core.decoupling.ErrorsHolder;
import cn.efunbox.afw.core.exception.AfwException;
import cn.efunbox.afw.core.exception.ValidationException;
import cn.efunbox.afw.core.mvc.context.Context;
import cn.efunbox.afw.core.util.MessageUtil;

/**
 * 类名：SimpleExceptionProcessor  <br />
 *
 * 功能：异常处理器基础实现
 *
 * @author xtwin <br />
 * 创建时间：2015年12月4日 上午11:42:02  <br />
 * @version 2015年12月4日
 */
public class SimpleExceptionProcessor implements ExceptionProcessor {
	
	// 未知错误代码
	private String unknownCode = "0900";

	/**
	 * 功能: <br/>
	 * 
	 * 重写：xtwin <br/>
	 * 
	 * @version ：2015年12月4日 上午11:42:23<br/>
	 * 
	 * @param context
	 * @param exp <br/>
	 * @see cn.efunbox.afw.core.exception.handler.ExceptionProcessor#process(cn.efunbox.afw.core.mvc.context.Context, java.lang.Exception)
	 */
	@Override
	public void process(Context context, Exception exp) {
		// 解析出错误实体
		ErrorModel error = resolveErrorModel(context, exp);
		
		// 将错误信息保存在上下文中
		((ErrorsHolder) context).setErrors(error);
		
		// 让子类做相关处理
		post(context, error, exp);
	}
	
	/**
	 * 
	 * 功能：供子类做相关处理 <br/>
	 *
	 * @author xtwin <br/>
	 * @version 2015年12月4日 上午11:46:35 <br/>
	 */
	protected void post(Context context, ErrorModel error, Exception exp) {
		// 默认为空实现
	}

	/**
	 * 
	 * 功能： <br/>
	 *
	 * @author xtwin <br/>
	 * @version 2015年12月4日 上午11:45:34 <br/>
	 */
	protected ErrorModel resolveErrorModel(Context context, Exception ex) {
		// 解析出当前的国际化语言信息
		Locale locale = context.getLocale();
		
		// 错误码
		String code = null;
		// 参数集合
		String[] i18Parameters = null;
		Object[] parameters = null;
		if (ex instanceof AfwException) {
			// 取得错误码
			code = ((AfwException) ex).getCode();
			
			// 对占位符参数做处理
			parameters = ((AfwException) ex).getParameters();
			if (null != parameters && parameters.length > 0) {
				i18Parameters = new String[parameters.length];
				
				// 翻译占位符
				for (int i = 0, len = parameters.length; i < len; i++) {
					Object p = parameters[i];
					
					if (null != p && (p instanceof String)) {
						p = MessageUtil.getMessage("dictionary." + p, null, locale, (String) p);
					}
					
					i18Parameters[i] = String.valueOf(p);
				}
			}
		} else {
			// 未知错误
			code = unknownCode;
		}
		
		// 创建错误实体
		ErrorModel error = new ErrorModel();
		
		// 放入错误码
		error.setCode(code);
		// 放入异常对象
		error.setException(ex);
		// 放入错误参数
		error.setParameters(parameters);
		// 放入翻译后的参数
		error.setI18Parameters(i18Parameters);
		// 放入错误消息
		error.setMessage(MessageUtil.getMessage(ex.getMessage(), i18Parameters, locale));
		
		// 校验异常特殊处理
		if (ex instanceof ValidationException) {
			// 消息
			String message = error.getMessage();
			
			// 校验异常，将字段错误信息放入model中
			Map<String, ErrorField> fields = new HashMap<String, ErrorField>();
			
			// TODO 暂时只会报单个字段的错误，这里先这样处理
			if (null != parameters && parameters.length > 0) {
				for (int i = 0, len = parameters.length; i < len; i++) {
					// 取出字段
					String field = String.valueOf(parameters[i]);
					
					// 放入字段
					fields.put(field, new ErrorField(field, i18Parameters[i], message));
				}
			}
			
			// 放入错误字段信息
			error.setFields(fields);
		}
		
		return error;
	}
}
